//
//  demo1.swift
//  swift_closure
//
//  Created by chenyh on 2021/1/15.
//

import Foundation
import UIKit
import os

let logger = OSLog.init(subsystem: "com.example.Fruta", category: "giftcards")







@dynamicMemberLookup
struct Material {

 public var roughness: Float
 public var color: CGFloat

    @CopyOnWrite public var texture: Texture
 
 }
@propertyWrapper
struct CopyOnWrite<Value: Copyable> {
    init(initialValue: Value) {
        store = initialValue
    }

    private var store: Value

    var value: Value {
        mutating get {
            if !isKnownUniquelyReferenced(&amp;store) {
                store = store.copy()
            }
            return store
        }
        set { store = newValue }
    }
}

    
class Texture: NSObject {
    var isSparkly: Bool = false
    var runlimit: String?
}
extension Texture: Copyable {
    
}
func doSomting() {
    let t = Texture()
    let m = Material(roughness: 0, color: 0, _texture: t)
 
}

public struct MyType {
 
 var textStorage: String? = nil
 
 @LateInitialized public var text: String
 
}
//    PropertyWrapper 顾名思义：属性包装器

@propertyWrapper
public struct LateInitialized<Value> {
    private var storage: Value?
    public var value: Value {
        get {
            guard let value = storage else {
                fatalError("value has not yet been set!")
            }
            return value
        }
        set {storage = newValue}
    }
}

/**
 DynamicMemberLookup 简化动态成员属性调用

 PropertyWrapper 让属性可以自定义注解，统一属性模板代码并且提供文档化的书写方式
 */
struct Topic {
    var title: String = "hello word"
    var content: String = "h"
}
struct TopicViewer: View {
    @State private var isEditing = false
    @Binding var topic: Topic
    var body: some View {
        VStack {
            Text("Title:\($topic.title)")
            if isEditing {
                TextField(topic.content)
            }
        }
    }
}


struct Video: Decodable {
    let id: Int
    let title: String
    @Default.False  var commentEnableed: Bool
    @Default<State>
    var state: State
    enum State: String,Decodable {
        case a
        case b
        case unknown
    }
}

@propertyWrapper
struct Default<T: DefaultValue> {
    var wrappedValue: T.Value
}
extension Default: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let v = (try? container.decode(T.Value.self)) ?? T.defaultValue
        self.wrappedValue = v
    }
}
extension Default {
    typealias True = Default<Bool.True>
    typealias False = Default<Bool.False>
}
protocol DefaultValue {
    associatedtype Value: Decodable
    static var defaultValue: Value {get}
}
extension Bool {
   
    enum False: DefaultValue {
        static let defaultValue = false
    }
    enum True: DefaultValue {
        static let defaultValue = true
    }
}
extension Video.State: DefaultValue {
    static let defaultValue = Video.State.unknown
}
extension KeyedDecodingContainer {
    func decode<T>(
            _ type: Default<T>.Type,
            forKey key: Key
        ) throws -> Default<T> where T: DefaultValue {
            try decodeIfPresent(type, forKey: key) ?? Default(wrappedValue: T.defaultValue)
        }
}


